<?php

declare(strict_types=1);

namespace App\Services;

use App\Services\Database;

final class SettingsService
{
    private static array $cache = [];
    private static ?SettingsService $instance = null;

    public static function getInstance(): self
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    public static function get(string $key, $default = null)
    {
        if (isset(self::$cache[$key])) {
            return self::$cache[$key];
        }

        try {
            $db = Database::pdo();

            // 确保设置表存在
            self::ensureSettingsTable();

            $stmt = $db->prepare("SELECT value FROM settings WHERE `key` = :key");
            $stmt->bindParam(':key', $key);
            $stmt->execute();

            $result = $stmt->fetch(\PDO::FETCH_ASSOC);
            $value = $result ? $result['value'] : $default;

            // 尝试解析 JSON
            $decoded = json_decode($value, true);
            if (json_last_error() === JSON_ERROR_NONE) {
                $value = $decoded;
            }

            self::$cache[$key] = $value;
            return $value;
        } catch (\Throwable $e) {
            error_log("Settings get error: " . $e->getMessage());
            return $default;
        }
    }

    public static function set(string $key, $value): bool
    {
        try {
            $db = Database::pdo();

            // 确保设置表存在
            self::ensureSettingsTable();

            // 如果是数组或对象，转换为 JSON
            if (is_array($value) || is_object($value)) {
                $value = json_encode($value, JSON_UNESCAPED_UNICODE);
            }

            $stmt = $db->prepare("
                INSERT INTO settings (`key`, `value`, `updated_at`) 
                VALUES (:key, :value, NOW()) 
                ON DUPLICATE KEY UPDATE 
                `value` = VALUES(`value`), 
                `updated_at` = VALUES(`updated_at`)
            ");

            $stmt->bindParam(':key', $key);
            $stmt->bindParam(':value', $value);
            $result = $stmt->execute();

            // 更新缓存
            if ($result) {
                self::$cache[$key] = is_string($value) && json_decode($value, true) !== null ? json_decode($value, true) : $value;
            }

            return $result;
        } catch (\Throwable $e) {
            error_log("Settings set error: " . $e->getMessage());
            return false;
        }
    }

    public static function getAll(): array
    {
        try {
            $db = Database::pdo();

            // 确保设置表存在
            self::ensureSettingsTable();

            $stmt = $db->query("SELECT `key`, `value` FROM settings ORDER BY `key`");
            $results = $stmt->fetchAll(\PDO::FETCH_ASSOC);

            $settings = [];
            foreach ($results as $row) {
                $value = $row['value'];
                $decoded = json_decode($value, true);
                if (json_last_error() === JSON_ERROR_NONE) {
                    $value = $decoded;
                }
                $settings[$row['key']] = $value;
            }

            return $settings;
        } catch (\Throwable $e) {
            error_log("Settings getAll error: " . $e->getMessage());
            return [];
        }
    }

    public static function getDefaults(): array
    {
        return [
            'site_name' => 'MyCMS',
            'site_description' => '一个简单的内容管理系统',
            'posts_per_page' => 10,
            'allow_registration' => true,
            'maintenance_mode' => false,
            'admin_email' => '',
            'timezone' => 'Asia/Shanghai'
        ];
    }

    public static function initializeDefaults(): bool
    {
        $defaults = self::getDefaults();
        $success = true;

        foreach ($defaults as $key => $value) {
            if (self::get($key) === null) {
                if (!self::set($key, $value)) {
                    $success = false;
                }
            }
        }

        return $success;
    }

    private static function ensureSettingsTable(): void
    {
        static $tableChecked = false;

        if ($tableChecked) {
            return;
        }

        try {
            $db = Database::pdo();

            $db->exec("
                CREATE TABLE IF NOT EXISTS settings (
                    `key` VARCHAR(100) PRIMARY KEY,
                    `value` TEXT,
                    `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                    `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
            ");

            $tableChecked = true;
        } catch (\Throwable $e) {
            error_log("Settings table creation error: " . $e->getMessage());
        }
    }
}
